package com.gupao.study.interpreter.calculate;

import java.util.Stack;

/**
 * 计算器
 */
public class GPCalculator {
    private Stack<IArithmeticInterpreter> stack = new Stack<IArithmeticInterpreter>();
    private Stack<IArithmeticInterpreter> bracketsStack = new Stack<IArithmeticInterpreter>();

    public GPCalculator(String expression) {
        this.parse(expression);
    }

    private void parse(String expression) {
        String [] elements = expression.split(" ");
        IArithmeticInterpreter leftExpr, rightExpr;

        for (int i = 0; i < elements.length ; i++) {
            String operator = elements[i];
            // 计算括号中的值
            i =  brackets(operator,i,elements);
            if (OperatorUtil.isOperator(operator)){
                leftExpr = this.stack.pop();
                String newOperator = elements[++i];
                // 计算括号中的值
                i =  brackets(newOperator,i,elements);
                if(this.bracketsStack.empty()){
                    rightExpr = new NumInterpreter(Integer.valueOf(newOperator));
                }else{
                    rightExpr = this.bracketsStack.pop();
                }
                //System.out.println("出栈: " + leftExpr.interpret() + " 和 " + rightExpr.interpret());
                this.stack.push(OperatorUtil.getInterpreter(leftExpr, rightExpr,operator));
                //System.out.println("应用运算符: " + operator);
            }
            else{
                NumInterpreter numInterpreter = new NumInterpreter(Integer.valueOf(elements[i]));
                this.stack.push(numInterpreter);
                //System.out.println("入栈: " + numInterpreter.interpret());
            }
        }
    }

    /**
     * 计算括号中的值目前只支持 1个括号
     * @param operator
     * @param i
     * @param elements
     * @return 返回下标
     */
    public int brackets(String operator,int i,String[] elements){
        if(OperatorUtil.isLeftBrackets(operator)){
            //括号中的第1个值入栈
            bracketsStack.push(new NumInterpreter(Integer.valueOf(elements[++i])));
            for(;i < elements.length ; i++){
                operator = elements[++i];
                if(OperatorUtil.isRightBrackets(operator)){
                    break;
                }
                if (OperatorUtil.isOperator(operator)){
                    IArithmeticInterpreter leftExpr = this.bracketsStack.pop();
                    IArithmeticInterpreter rightExpr = new NumInterpreter(Integer.valueOf(elements[++i]));
                    NumInterpreter num = new NumInterpreter(OperatorUtil.getInterpreter(leftExpr, rightExpr,operator).interpret());
                    this.bracketsStack.push(num);
                    i--;
                }
            }
        }
        return i;
    }

    public int calculate() {
        return this.stack.pop().interpret();
    }
}